/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.alibaba.dubboadmin;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.web.context.WebApplicationContext;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Optional;

/**
 * dubbo管理应用程序
 *
 * @author wangxin4
 * @date 2024/05/14 17:26
 */
@SpringBootApplication
public class DubboAdminApplication {

    private static final Logger log = LoggerFactory.getLogger(DubboAdminApplication.class);

    public static void main(String[] args) {
        ApplicationContext act = SpringApplication.run(DubboAdminApplication.class, args);
        SpringUtil.setApplicationContext(act);
        printApplicationInfo(act);
    }

    /**
     * 打印应用程序启动信息，包括SpringBoot版本，应用程序版本和本地URL。
     *
     * @param context 应用程序上下文
     */
    private static void printApplicationInfo(ApplicationContext context) {
        String applicationInfo = buildApplicationInfo();
        Optional<String> hostAddress = getLocalHostAddress();

        if (isWebApplicationContext(context) && hostAddress.isPresent()) {
            String localUrl = buildLocalUrl(context, hostAddress.get());
            applicationInfo += localUrl;
        }
        applicationInfo += "\n\tdubbo-admin start successful\n";
        log.info(applicationInfo);
    }

    /**
     * 构建应用程序信息，包括SpringBoot版本和应用程序版本。
     *
     * @return 应用程序信息
     */
    private static String buildApplicationInfo() {
        return "\n\n\tSpringBoot Version: " + org.springframework.boot.SpringBootVersion.getVersion()
                + "\n\tApplication Version: " + DubboAdminApplication.class.getPackage().getImplementationVersion();
    }

    /**
     * 获取本地主机地址。
     *
     * @return 本地主机地址
     */
    private static Optional<String> getLocalHostAddress() {
        try {
            return Optional.of(InetAddress.getLocalHost().getHostAddress());
        } catch (UnknownHostException e) {
            return Optional.empty();
        }
    }

    /**
     * 检查给定的上下文是否是WebApplicationContext的实例。
     *
     * @param context 应用程序上下文
     * @return 如果上下文是WebApplicationContext的实例，则返回true，否则返回false
     */
    private static boolean isWebApplicationContext(ApplicationContext context) {
        return context instanceof WebApplicationContext;
    }

    /**
     * 使用给定的上下文和主机地址构建本地URL。
     *
     * @param context     应用程序上下文
     * @param hostAddress 主机地址
     * @return 本地URL
     */
    private static String buildLocalUrl(ApplicationContext context, String hostAddress) {
        Environment environment = context.getEnvironment();
        int serverPort = environment.getProperty("server.port", Integer.class, 8080);
        String contextPath = environment.getProperty("server.servlet.context-path");
        return "\n\tLocal URL: http://" + hostAddress + ":" + serverPort + contextPath;
    }
}
